/* Copyright (c) 2010, Carl Burch. License information is located in the
 * com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.logisim.std.base;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Font;
import java.awt.Rectangle;

import com.cburch.logisim.comp.TextField;
import com.cburch.logisim.data.Attribute;
import com.cburch.logisim.data.AttributeOption;
import com.cburch.logisim.data.AttributeSet;
import com.cburch.logisim.data.Attributes;
import com.cburch.logisim.data.Bounds;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.instance.Instance;
import com.cburch.logisim.instance.InstanceFactory;
import com.cburch.logisim.instance.InstancePainter;
import com.cburch.logisim.instance.InstanceState;
import com.cburch.logisim.util.GraphicsUtil;
import static com.cburch.logisim.util.LocaleString.*;

public class Text extends InstanceFactory {
    public static Attribute<String> ATTR_TEXT = Attributes.forString("text",
            getFromLocale("textTextAttr"));
    public static Attribute<Font> ATTR_FONT = Attributes.forFont("font",
        getFromLocale("textFontAttr"));
    public static Attribute<AttributeOption> ATTR_HALIGN = Attributes.forOption("halign",
        getFromLocale("textHorzAlignAttr"), new AttributeOption[] {
            new AttributeOption(Integer.valueOf(TextField.H_LEFT),
                "left", getFromLocale("textHorzAlignLeftOpt")),
            new AttributeOption(Integer.valueOf(TextField.H_RIGHT),
                "right", getFromLocale("textHorzAlignRightOpt")),
            new AttributeOption(Integer.valueOf(TextField.H_CENTER),
                "center", getFromLocale("textHorzAlignCenterOpt")),
        });
    public static Attribute<AttributeOption> ATTR_VALIGN = Attributes.forOption("valign",
        getFromLocale("textVertAlignAttr"), new AttributeOption[] {
            new AttributeOption(Integer.valueOf(TextField.V_TOP),
                "top", getFromLocale("textVertAlignTopOpt")),
            new AttributeOption(Integer.valueOf(TextField.V_BASELINE),
                "base", getFromLocale("textVertAlignBaseOpt")),
            new AttributeOption(Integer.valueOf(TextField.V_BOTTOM),
                "bottom", getFromLocale("textVertAlignBottomOpt")),
            new AttributeOption(Integer.valueOf(TextField.H_CENTER),
                "center", getFromLocale("textVertAlignCenterOpt")),
        });

    public static final Text FACTORY = new Text();

    private Text() {
        super("Text", getFromLocale("textComponent"));
        setIconName("text.svg");
        setShouldSnap(false);
    }

    @Override
    public AttributeSet createAttributeSet() {
        return new TextAttributes();
    }

    @Override
    public Bounds getOffsetBounds(AttributeSet attrsBase) {
        TextAttributes attrs = (TextAttributes) attrsBase;
        String text = attrs.getText();
        if (text == null || text.equals("")) {
            return Bounds.EMPTY_BOUNDS;
        } else {
            Bounds bds = attrs.getOffsetBounds();
            if (bds == null) {
                bds = estimateBounds(attrs);
                attrs.setOffsetBounds(bds);
            }
            return bds == null ? Bounds.EMPTY_BOUNDS : bds;
        }
    }

    private Bounds estimateBounds(TextAttributes attrs) {
        // TODO - you can imagine being more clever here
        String text = attrs.getText();
        if (text == null || text.length() == 0) {
            return Bounds.EMPTY_BOUNDS;
        }

        int size = attrs.getFont().getSize();
        int h = size;
        int w = size * text.length() / 2;
        int ha = attrs.getHorizontalAlign();
        int va = attrs.getVerticalAlign();
        int x;
        int y;
        if (ha == TextField.H_LEFT) {
            x = 0;
        } else if (ha == TextField.H_RIGHT) {
            x = -w;
        } else {
            x = -w / 2;
        }
        if (va == TextField.V_TOP) {
            y = 0;
        } else if (va == TextField.V_CENTER) {
            y = -h / 2;
        } else {
            y = -h;
        }
        return Bounds.create(x, y, w, h);
    }

    //
    // graphics methods
    //
    @Override
    public void paintGhost(InstancePainter painter) {
        TextAttributes attrs = (TextAttributes) painter.getAttributeSet();
        String text = attrs.getText();
        if (text == null || text.equals("")) {
            return;
        }


        int halign = attrs.getHorizontalAlign();
        int valign = attrs.getVerticalAlign();
        Graphics g = painter.getGraphics();
        Font old = g.getFont();
        g.setFont(attrs.getFont());
        GraphicsUtil.drawText(g, text, 0, 0, halign, valign);

        String textTrim = text.endsWith(" ") ? text.substring(0, text.length() - 1) : text;
        Bounds newBds;
        if (textTrim.equals("")) {
            newBds = Bounds.EMPTY_BOUNDS;
        } else {
            Rectangle bdsOut = GraphicsUtil.getTextBounds(g, textTrim, 0, 0,
                    halign, valign);
            newBds = Bounds.create(bdsOut).expand(4);
        }
        if (attrs.setOffsetBounds(newBds)) {
            Instance instance = painter.getInstance();
            if (instance != null) {
                instance.recomputeBounds();
            }

        }

        g.setFont(old);
    }

    @Override
    public void paintInstance(InstancePainter painter) {
        Location loc = painter.getLocation();
        int x = loc.getX();
        int y = loc.getY();
        Graphics g = painter.getGraphics();
        g.translate(x, y);
        g.setColor(Color.BLACK);
        paintGhost(painter);
        g.translate(-x, -y);
    }

    //
    // methods for instances
    //
    @Override
    protected void configureNewInstance(Instance instance) {
        configureLabel(instance);
        instance.addAttributeListener();
    }

    @Override
    protected void instanceAttributeChanged(Instance instance, Attribute<?> attr) {
        if (attr == ATTR_HALIGN || attr == ATTR_VALIGN) {
            configureLabel(instance);
        }
    }

    private void configureLabel(Instance instance) {
        TextAttributes attrs = (TextAttributes) instance.getAttributeSet();
        Location loc = instance.getLocation();
        instance.setTextField(ATTR_TEXT, ATTR_FONT, loc.getX(), loc.getY(),
                attrs.getHorizontalAlign(), attrs.getVerticalAlign());
    }

    @Override
    public void propagate(InstanceState state) { }
}
